
#include "pow_custom_tiling.h"
#include "register/op_def_registry.h"
#include "graph/utils/type_utils.h"
#include "tiling/platform/platform_ascendc.h"
#include <vector>
#include <algorithm> 
#include "graph/types.h" 

namespace optiling {
const uint32_t BLOCK_SIZE = 256;
const uint32_t BUFFER_NUM = 2;
static ge::graphStatus TilingFunc(gert::TilingContext* context)
{
    TilingData tiling;
    uint64_t ubSize;
    auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo());
    ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize);
    // auto coreNum = ascendcPlatform.GetCoreNum();
    auto coreNum = 8;

    // ======== 基本输入信息 ========
    uint32_t inputNum = context->GetOutputShape(0)->GetStorageShape().GetShapeSize();
    
    uint32_t typeLength0 = 0;
    ge::TypeUtils::GetDataTypeLength(context->GetInputDesc(0)->GetDataType(), typeLength0);
    uint32_t typeLength1 = 0;
    ge::TypeUtils::GetDataTypeLength(context->GetInputDesc(1)->GetDataType(), typeLength1);
    uint32_t outputTypeLength = 0;
    ge::TypeUtils::GetDataTypeLength(context->GetOutputDesc(0)->GetDataType(), outputTypeLength);
    uint32_t typeLength = std::max(std::max(typeLength0, typeLength1),std::max(outputTypeLength, uint32_t(1)));
 
    uint32_t inputLength = inputNum * typeLength;
    uint32_t inputBytes = inputLength / inputNum;

    // ======== UB划分策略 ========
    uint32_t ubDataNumber = (typeLength1 == 1 && typeLength0 == 1)? 24 : 12 ;

    uint32_t tileBlockNum = (ubSize / BLOCK_SIZE / BUFFER_NUM) / ubDataNumber;
    uint32_t tileDataNum = (tileBlockNum * BLOCK_SIZE) / inputBytes;

    uint32_t inputLengthAlign32 = (((inputLength + BLOCK_SIZE - 1) / BLOCK_SIZE) * BLOCK_SIZE);
    coreNum = (coreNum < inputLengthAlign32 / BLOCK_SIZE) ? coreNum : inputLengthAlign32 / BLOCK_SIZE;
    coreNum = (coreNum >= 1) ? coreNum : 1;
    uint32_t everyCoreInputBlockNum = inputLengthAlign32 / BLOCK_SIZE / coreNum;
    uint32_t tailBlockNum = (inputLengthAlign32 / BLOCK_SIZE) % coreNum;

    // ======== 小核 & 大核计算 ========
    uint32_t smallCoreDataNum = everyCoreInputBlockNum * BLOCK_SIZE / inputBytes;
    uint32_t smallTileNum = everyCoreInputBlockNum / tileBlockNum;
    uint32_t finalSmallTileNum = (everyCoreInputBlockNum % tileBlockNum) == 0 ? smallTileNum : smallTileNum + 1;
    uint32_t smallTailDataNum = smallCoreDataNum - (tileDataNum * smallTileNum);
    smallTailDataNum = smallTailDataNum == 0 ? tileDataNum : smallTailDataNum;

    everyCoreInputBlockNum += 1;
    uint32_t bigCoreDataNum = everyCoreInputBlockNum * BLOCK_SIZE / inputBytes;
    uint32_t bigTileNum = everyCoreInputBlockNum / tileBlockNum;
    uint32_t finalBigTileNum = (everyCoreInputBlockNum % tileBlockNum) == 0 ? bigTileNum : bigTileNum + 1;
    uint32_t bigTailDataNum = bigCoreDataNum - tileDataNum * bigTileNum;
    bigTailDataNum = bigTailDataNum == 0 ? tileDataNum : bigTailDataNum;

    // ======== 设置Tiling字段 ========
    tiling.set_smallCoreDataNum(smallCoreDataNum);
    tiling.set_bigCoreDataNum(bigCoreDataNum);
    tiling.set_tileDataNum(tileDataNum);
    tiling.set_smallTailDataNum(smallTailDataNum);
    tiling.set_bigTailDataNum(bigTailDataNum);
    tiling.set_finalSmallTileNum(finalSmallTileNum);
    tiling.set_finalBigTileNum(finalBigTileNum);
    tiling.set_tailBlockNum(tailBlockNum);

    // ======== 数据类型 ========
    auto input0_dtype = static_cast<int32_t>(context->GetInputDesc(0)->GetDataType());
    auto input1_dtype = static_cast<int32_t>(context->GetInputDesc(1)->GetDataType());
    auto output_dtype = static_cast<int32_t>(context->GetOutputDesc(0)->GetDataType());
    tiling.set_x_dtype(input0_dtype);
    tiling.set_y_dtype(input1_dtype);
    tiling.set_z_dtype(output_dtype);

    // ======== 判断标量输入 ========
    bool is_input0_scalar = (context->GetInputShape(0)->GetStorageShape().GetShapeSize() == 1);
    bool is_input1_scalar = (context->GetInputShape(1)->GetStorageShape().GetShapeSize() == 1);
    tiling.set_is_input0_scalar(is_input0_scalar);
    tiling.set_is_input1_scalar(is_input1_scalar);

         // ======== 输入形状 ========
    const int maxDims = 10; 
    uint32_t x1ShapeArr[maxDims] = {0};
    uint32_t x2ShapeArr[maxDims] = {0};
    uint32_t yShapeArr[maxDims] = {0};
    const gert::Shape x1ShapeObj = context->GetInputShape(0)->GetStorageShape();
    const gert::Shape x2ShapeObj = context->GetInputShape(1)->GetStorageShape();
    uint32_t dimNum1 = x1ShapeObj.GetDimNum();
    uint32_t dimNum2 = x2ShapeObj.GetDimNum();
    uint32_t dimMax  = (dimNum1 > dimNum2) ? dimNum1 : dimNum2;
    uint32_t X1TotalNum = 1;
    uint32_t X2TotalNum = 1;
    for (uint32_t i = 0; i < dimNum1; ++i) {
        x1ShapeArr[i] = static_cast<uint32_t>(x1ShapeObj.GetDim(i));
        X1TotalNum *= x1ShapeArr[i];
    }
     for (uint32_t i = 0; i < dimNum2; ++i) {
        x2ShapeArr[i] = static_cast<uint32_t>(x2ShapeObj.GetDim(i));
        X2TotalNum *= x2ShapeArr[i];
    }
    tiling.set_X1TotalNum(X1TotalNum);
    tiling.set_X2TotalNum(X2TotalNum);

    // ======== 广播后的输出形状 ========
    // 从最后一维开始对齐（NumPy广播规则）
    for (int i = 0; i < dimMax; ++i) {
        int idx1 = dimNum1 - 1 - i;
        int idx2 = dimNum2 - 1 - i;
        uint32_t s1 = (idx1 >= 0) ? x1ShapeObj.GetDim(idx1) : 1;
        uint32_t s2 = (idx2 >= 0) ? x2ShapeObj.GetDim(idx2) : 1;
       if (s1 != s2 && s1 != 1 && s2 != 1) {
            std::cout << "Broadcast Fail,Please check your input shape" << std::endl;
            return ge::GRAPH_FAILED;
        }
        yShapeArr[dimMax  - 1 - i] = (s1 > s2) ? s1 : s2;
    }
    // ======== 判断输入与输出形状是否一致 ========
    bool isSameX1 = true;
    bool isSameX2 = true;
    for (int i = 0; i < dimMax; ++i) {
        if (x1ShapeArr[i] != yShapeArr[i]) {
            isSameX1 = false;
        }
        if (x2ShapeArr[i] != yShapeArr[i]) {
            isSameX2 = false;
        }
    }
    if(dimNum1 != dimMax)isSameX1 = false;
    if(dimNum2 != dimMax)isSameX2 = false;
    tiling.set_isSameX1(isSameX1);
    tiling.set_isSameX2(isSameX2);

    // ===============================================
    // Host 端预计算广播 stride（右对齐 + 安全补齐）
    // ===============================================
    // 创建副本并右对齐 shape
    uint32_t alignedX1[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    uint32_t alignedX2[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    uint32_t alignedY[10]  = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};

    for (int i = 0; i < dimNum1; ++i)
        alignedX1[dimMax - dimNum1 + i] = x1ShapeArr[i];
    for (int i = 0; i < dimNum2; ++i)
        alignedX2[dimMax - dimNum2 + i] = x2ShapeArr[i];
    for (int i = 0; i < dimMax; ++i)
        alignedY[i] = yShapeArr[i];

    uint32_t strideX1[10] = {0};
    uint32_t strideX2[10] = {0};
    uint32_t strideY[10]  = {0};
    // 输出 stride
    strideY[dimMax - 1] = 1;
    for (int i = dimMax - 2; i >= 0; --i)
        strideY[i] = strideY[i + 1] * alignedY[i + 1];

    // 计算 x1/x2 stride（按对齐后 shape）
    strideX1[dimMax - 1] = 1;
    strideX2[dimMax - 1] = 1;
    for (int i = dimMax - 2; i >= 0; --i) {
        strideX1[i] = strideX1[i + 1] * alignedX1[i + 1];
        strideX2[i] = strideX2[i + 1] * alignedX2[i + 1];
    }

    // 根据广播规则计算有效 stride
    uint32_t effStrideX1[10] = {0};
    uint32_t effStrideX2[10] = {0};
    for (int i = 0; i < dimMax; ++i) {
        effStrideX1[i] = (alignedX1[i] == 1) ? 0 : strideX1[i];
        effStrideX2[i] = (alignedX2[i] == 1) ? 0 : strideX2[i];
    }
    tiling.set_yDim(dimMax);
    tiling.set_strideX1(effStrideX1);
    tiling.set_strideX2(effStrideX2);
    tiling.set_strideY(strideY);




    // ======== 保存结果 ========
    context->SetBlockDim(coreNum);
    tiling.SaveToBuffer(context->GetRawTilingData()->GetData(), context->GetRawTilingData()->GetCapacity());
    context->GetRawTilingData()->SetDataSize(tiling.GetDataSize());

    size_t* currentWorkspace = context->GetWorkspaceSizes(1);
    currentWorkspace[0] = 0;
    return ge::GRAPH_SUCCESS;
}
}
namespace ge {
static graphStatus InferShape(gert::InferShapeContext *context)
{
    auto x1_shape = context->GetInputShape(0);
    auto x2_shape = context->GetInputShape(1);
    auto y_shape  = context->GetOutputShape(0);

    const auto &Dim1 = *x1_shape;
    const auto &Dim2 = *x2_shape;

    int dimNum1 = Dim1.GetDimNum();
    int dimNum2 = Dim2.GetDimNum();
    int maxDim  = std::max(dimNum1, dimNum2);

    std::vector<int64_t> outDims(maxDim, 1);

    // 从最后一个维度开始匹配广播
    for (int i = 0; i < maxDim; i++) {
        int64_t d1 = (i < dimNum1) ? Dim1.GetDim(dimNum1 - 1 - i) : 1;
        int64_t d2 = (i < dimNum2) ? Dim2.GetDim(dimNum2 - 1 - i) : 1;
        if (d1 == d2 || d1 == 1 || d2 == 1) {
            outDims[maxDim - 1 - i] = std::max(d1, d2);
        } else {
            // 维度不匹配，返回推理失败
            return GRAPH_FAILED;
        }
    }
     // 设置输出形状
    gert::Shape outShape;
    for (size_t i = 0; i < outDims.size(); ++i) {
        outShape.AppendDim(outDims[i]);
    }
    *y_shape = outShape;

    return GRAPH_SUCCESS;
}

static graphStatus InferDataType(gert::InferDataTypeContext *context)
{
    auto dtype1 = context->GetInputDataType(0);
    auto dtype2 = context->GetInputDataType(1);
    auto getPriority = [](ge::DataType dt) -> int {
            switch (dt) {
                case ge::DT_INT8:     return 1;
                case ge::DT_UINT8:    return 2;
                case ge::DT_INT16:    return 3;
                case ge::DT_INT32:    return 4;
                case ge::DT_FLOAT16:  return 5;
                case ge::DT_BF16:     return 6;
                case ge::DT_FLOAT:    return 7;
                default:              return 0; // unsupported
            }
    };

    int p1 = getPriority(dtype1);
    int p2 = getPriority(dtype2);

    // 默认选优先级更高的类型
    ge::DataType outType = (p1 >= p2) ? dtype1 : dtype2;

    // 针对特殊情况修正
    if ((dtype1 == ge::DT_FLOAT16 && dtype2 == ge::DT_BF16) ||
        (dtype1 == ge::DT_BF16 && dtype2 == ge::DT_FLOAT16)) {
        outType = ge::DT_FLOAT; // FP16 + BF16 → FP32
    } else if ((dtype1 == ge::DT_INT8 && dtype2 == ge::DT_UINT8) ||
            (dtype1 == ge::DT_UINT8 && dtype2 == ge::DT_INT8)) {
        outType = ge::DT_INT16; // INT8 + UINT8 → INT16
    }

    context->SetOutputDataType(0, outType);
    return ge::GRAPH_SUCCESS;
}
} // namespace ge

namespace ops {
class PowCustom : public OpDef {
public:
    explicit PowCustom(const char *name) : OpDef(name)
    {
        this->Input("x1")
            .ParamType(REQUIRED)
            .DataType({ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT})
            .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
            .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
        this->Input("x2")
            .ParamType(REQUIRED)
            .DataType({ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT})
            .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
            .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
        this->Output("y")
            .ParamType(REQUIRED)
            .DataType({ge::DT_INT8, ge::DT_INT16, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT16, ge::DT_UINT8, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT})
            .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
            .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});


        this->SetInferShape(ge::InferShape).SetInferDataType(ge::InferDataType);

        this->AICore()
            .SetTiling(optiling::TilingFunc);
        this->AICore().AddConfig("ascend910b");
    }
};
OP_ADD(PowCustom);
} // namespace ops
